
#include "systick.h"

// Systick 寄存器
// -> LOAD 系统重载值寄存器
// -> VAL 系统当前值寄存器 (重载值递减为0触发中断）

// { 系统定时器 }

// SysTickMS 已开机运行时间（毫秒）
volatile uint32 SysTickMS = 0;

#define SysTickHz        100U
#define SysTickVal_100MS (uint32)(SystemCoreClock / 10U)   // 1000Hz
#define SysTickVal_1MS   (uint32)(SystemCoreClock / 1000U) // 1000Hz
#define SysTickVal_1US   (uint32)(SystemCoreClock / 1000000U)

void InitSysTick() {
    if (SysTick_Config(SysTickVal_100MS)) {
        /* capture error */
        while (1) {
        }
    }
    /* configure the systick handler priority */
    NVIC_SetPriority(SysTick_IRQn, 0x00U);
}

void SysTick_Handler(void) {
    SysTickMS += SysTickHz;
}

// { 基于系统定时器的延时函数 }

void Delay100MS(uint32_t ACount) {
    uint32_t oStopMS = SysTickMS + ACount * SysTickHz;
    while (SysTickMS < oStopMS) {
        __asm("NOP");
    }
}

void DoDelay(uint32 ACount, uint32 ATickUint) {
    uint32 oStart = SysTick->VAL;
    uint32 oTicks = (ATickUint * ACount) - 50U;
    uint32 oNow, oPass = 0;

    while (1) {

        oNow = SysTick->VAL;

        if (oNow > oStart) {
            oPass = SysTick->LOAD - oNow + oStart;
        } else {
            oPass = oStart - oNow;
        }

        if (oPass > oTicks) {
            break;
        }
    }
}

void DelayMS(uint32 ACount) {

    uint32 oDelay = ACount % SysTickHz;
    if (oDelay > 0) {
        DoDelay(oDelay, SysTickVal_1MS);
    }
    ACount = ACount / SysTickHz;

    if (ACount == 0) {
        return;
    }

    Delay100MS(ACount);
}

void DelayUS(uint32 ACount) {

    if (ACount >= 1000) {
        DelayMS(ACount / 1000);
        ACount = ACount % 1000;
        if (ACount == 0) {
            return;
        }
    }

    DoDelay(ACount, SysTickVal_1US);
}

// { 基于系统定时器的超时判断函数 }

uint32 GetSysTickMS() {
    return SysTickMS;
}

void SetDueTickMS(pUint32 AValue, uint32 AGap) {
    *AValue = GetSysTickMS() + AGap;
}

bool SysTickAfter(uint32 ATickMS) {
    return SysTickMS > ATickMS;
}